package com.xuzhiguang.light.gateway.core.handler;

import com.xuzhiguang.light.gateway.common.handler.AbstractGatewayRequestHandler;
import com.xuzhiguang.light.gateway.common.handler.GatewayRequestHandler;
import com.xuzhiguang.light.gateway.common.handler.GatewayRequestHandlerConfig;
import com.xuzhiguang.light.gateway.common.request.GatewayRequest;
import com.xuzhiguang.light.gateway.common.request.RequestContext;
import lombok.Data;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author xuzhiguang
 */
public class BlockingQueueGatewayRequestHandler extends AbstractGatewayRequestHandler<BlockingQueueGatewayRequestHandler.Config> {

    private static final String HANDLER_NAME = "blockingQueue";

    private final GatewayRequestHandler<?> handler;

    private ThreadPoolExecutor executor;

    public BlockingQueueGatewayRequestHandler(GatewayRequestHandler<?> handler) {
        super(BlockingQueueGatewayRequestHandler.Config.class);
        this.handler = handler;
    }

    @Override
    public void handle(GatewayRequest gatewayRequest, RequestContext requestContext) {
        this.executor.execute(() -> handler.handle(gatewayRequest, requestContext));
    }

    @Override
    public void init(BlockingQueueGatewayRequestHandler.Config config) {
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(config.getQueueCapacity());
        this.executor = new ThreadPoolExecutor(config.getCorePoolSize(), config.getMaximumPoolSize(), config.getKeepAliveTime(), TimeUnit.SECONDS, queue);

    }

    @Override
    public void shutdown() {
        this.executor.shutdown();
        this.handler.shutdown();
    }

    @Override
    public String getName() {
        return HANDLER_NAME;
    }

    @Data
    public static class Config implements GatewayRequestHandlerConfig {

        private int corePoolSize = Runtime.getRuntime().availableProcessors();

        private int maximumPoolSize = Runtime.getRuntime().availableProcessors();

        private int keepAliveTime = 60;

        private int queueCapacity = 10000;
    }
}
